function [data] = smooth_boundcond(data, span, dim, method, boundCond, smoothIterNum)
% SMOOTH_BOUNDCOND 带边界条件的平滑
%
% Input Arguments:
% data: 矩阵，待平滑的数据
% dim: 标量，待平滑的维数，默认为1
% boundCond: 字符串，指定在两端处数据不够时的处理方法，'repeat'表示在两端重复端点值，'reflect'表示反射两端数据，默认为'reflect'
% smoothIterNum: 平滑次数，默认为1
% 其它参数: 参见smooth的帮助
%
% Output Arguments:
% smoothData: 尺寸与data相同的矩阵，第dim维为data第dim维平滑后的数据

if nargin < 6
    smoothIterNum = 1;
end
if nargin < 5
    boundCond = 'reflect';
end
if nargin < 4
    method = 'moving';
end
if nargin < 3
    dim = 1;
end
if nargin < 2
    span = 5;
end

% 将待平滑维数重排至第1维以方便处理
order = 1:ndims(data); % FIXME: 输入为列向量时出错
order(1, 1) = dim;
order(1, dim) = 1;
data = permute(data, order);
sz = size(data);
nBlocks = prod(sz(1, 2:end));
blockLen = sz(1, 1);

% 循环处理每列数据
halfSpan = floor(span/2);
for i=1:nBlocks
    % 处理边界
    colData = data(((i-1)*blockLen+1):(i*blockLen))'; % NOTE: 使用线性索引，假设column-major索引
    switch lower(boundCond)
        case 'repeat'
            colData = [repmat(colData(1, 1), halfSpan, 1); colData; repmat(colData(end, 1), halfSpan, 1)];
        case 'reflect'
            colData = [flipud(colData(2:(halfSpan+1), 1)); colData; flipud(colData((end-halfSpan):(end-1), 1))];
        otherwise
            error('Boundary condition invalid.');
    end
    
    % 平滑
    smoothedColData = colData;
    for j=1:smoothIterNum
        smoothedColData = smooth(smoothedColData, span, method);
    end
    data(((i-1)*blockLen+1):(i*blockLen)) = smoothedColData((halfSpan+1):(end-halfSpan), :); % TODO: check +-1
end

% 恢复维数排序
data = permute(data, order);
end